// Created By:      Roy Kravitz
// Modified By:     Jabeer Ahmed
// Last Modified:   (JA) 23-Jan-2014
//
// Revision History:
// -----------------
// Nov-2008     RK      Created this module for the S3E Starter Board
// Apr-2012     DG      Modified for Nexys 3 board
// Dec-2014     RJ      Cleaned up formatting.  No functional changes
// Jan-2014     JA      Converting Getting Started Guide to RojoBot project - 1
// 
// Description:
// ------------
// Top level module for the ECE 540 Project - 1 (RojoBot), built 
// on the Nexys3 FPGA Board (Xilinx XC6LX16-CS324). The module contains:
//      * BotSim (Rojo Bot)
//      * Picoblaze CPU - to run RojoBot control/path navigation logic
//      * Interface unit between BotSim <-> Picoblaze controls and sensors
//      * Nexys3 Pushbutton controller
//      * Nexys3 Slide switches controller
//      * Nexys3 Pushbutton controller
//
// Use the pushbuttons to control the Rojobot wheels:
//  btnl    Left wheel forward
//  btnu    Left wheel reverse
//  btnr    Right wheel forward
//  btnd    Right wheel reverse
//  btns    System reset
//
//  Switches are not used. Compass heading and a turn indicator 
//  are shown on the seven segment dispay.  LED's display the chase segments.  
///////////////////////////////////////////////////////////////////////////

module Nexys3fpga (
    // Inputs
    input               clk100,         // 100MHz clock from on-board oscillator
    input               btnl, btnr,     // pushbutton inputs - left and right
    input               btnu, btnd,     // pushbutton inputs - top and bottom
    input               btns,           // pushbutton inputs - center button
    input   [7:0]       sw,             // switch inputs
    // Outputs    
    output  [7:0]       led,            // LED outputs  
    output  [7:0]       seg,            // Seven segment display cathode pins
    output  [3:0]       an,             // Seven segment display anode pins     
    output  [3:0]       JA,             // JA Header

    output              Vsync,
    output              Hsync,
    output  [2:0]       vgaRed,
    output  [2:0]       vgaGreen,
    output  [2:0]       vgaBlue
); 
    
/*******************************************************************************
                            Internal Variables
 ******************************************************************************/
    wire                sysclk;         // 100MHz clock from on-board oscillator    
    wire                sysreset;       // system reset signal    
    wire    [31:0]      digits_out;     // ASCII digits (Only for Simulation)
    wire    [7:0]       db_sw;          // debounced switches
    wire    [4:0]       db_btns;        // debounced buttons

    /******************************* PicoBlaze ********************************/
    wire    [11:0]      pq_addr;
    wire    [17:0]      pq_instruction;
    wire                pq_bram_enable;
    wire    [7:0]       pq_port_id;
    wire    [7:0]       pq_out_port;
    wire    [7:0]       pq_in_port;
    wire                pq_write_strobe;
    wire                pq_k_write_strobe;
    wire                pq_read_strobe;
    wire                pq_interrupt;            
    wire                pq_interrupt_ack;   
    wire                pq_kcpsm6_sleep;         
    reg                 pq_kcpsm6_reset; 

    /********************************* BotSIM *********************************/ 
    wire    [7:0]       bot_motctl;
    wire    [7:0]       bot_locX;
    wire    [7:0]       bot_locY;
    wire    [7:0]       bot_botinfo;
    wire    [7:0]       bot_sensors;
    wire    [7:0]       bot_Imdist;
    wire    [7:0]       bot_rmdist;
    wire                bot_upd_sysregs;
	wire 	[3:0] 		bot_pbtn_db;

    /****************************** sevensegment ******************************/ 
    wire    [4:0]       ssd_d0_out;
    wire    [4:0]       ssd_d1_out;
    wire    [4:0]       ssd_d2_out;
    wire    [4:0]       ssd_d3_out;
    wire    [3:0]       ssd_dp_out;
    
    /**************************** Video Controller ****************************/
    wire    [9:0]       vc_vid_row_out;
    wire    [9:0]       vc_vid_col_out;
    wire    [1:0]       bot_world_pxl_out;

    /**************************** Debounce Module *****************************/

    // global assigns
    assign  sysclk      = clk100;
    assign  sysreset    = db_btns[0];
	assign 	bot_pbtn_db = db_btns[4:1];
    assign  JA          = {sysclk, sysreset, 2'b0};

/*******************************************************************************
                            Submodule Instantiation
 ******************************************************************************/

    /************************* PicoBlaze Embedded CPU *************************/
    kcpsm6 #(
        // defparams
        .interrupt_vector   (12'h3FF),
        .scratch_pad_memory_size(64),
        .hwbuild        (8'h00))
    PicoBlaze (
        // port connections
        .address        (pq_addr),
        .instruction    (pq_instruction),
        .bram_enable    (pq_bram_enable),
        .port_id        (pq_port_id),
        .write_strobe   (pq_write_strobe),
        .k_write_strobe (pq_k_write_strobe),
        .out_port       (pq_out_port),
        .read_strobe    (pq_read_strobe),
        .in_port        (pq_in_port),
        .interrupt      (pq_interrupt),
        .interrupt_ack  (pq_interrupt_ack),
        .reset          (kcpsm6_reset),
        .sleep          (pq_kcpsm6_sleep),
        .clk            (sysclk)
    ); 

    assign kcpsm6_sleep = 1'b0;
    // assign interrupt = 1'b0;
	 wire prog_reset;
	 assign kcpsm6_reset = prog_reset | sysreset;
	 
    proj1demo #(
        .C_FAMILY               ("S6"), //Family 'S6' or 'V6'
        .C_RAM_SIZE_KWORDS      (1),    //Program size '1', '2' or '4'
        .C_JTAG_LOADER_ENABLE   (1))    //Include JTAG Loader when set to '1' 
    proj1demo (                         //Name to match your PSM file
        .rdl            (prog_reset),
        .enable         (pq_bram_enable),
        .address        (pq_addr),
        .instruction    (pq_instruction),
        .clk            (sysclk)
    );


    /****************************** nexys3_bot_if *****************************/    
    nexys3_bot_if Bot_IF (

        /*********** kcpsm6 (PicoBlaze) ***********/
        .Wr_Strobe      (pq_write_strobe),                // Write stobe  (pq > bot_if)
        .Rd_Strobe      (pq_read_strobe),                 // Read strobe  (pq > bot_if)
        .AddrIn         (pq_port_id),                        // Address In   (pq > bot_if)
        .DataIn         (pq_out_port),                       // Data In      (pq > bot_if)
        .DataOut        (pq_in_port),                       // Data Out     (pq > bot_if)
        .interrupt_ack  (pq_interrupt_ack),
        .interrupt      (pq_interrupt),      

        /***************** BotSIM *****************/
        .MotCtl         (bot_motctl),
        .LocX           (bot_locX),   
        .LocY           (bot_locY),   
        .BotInfo        (bot_botinfo),
        .Sensors        (bot_sensors),
        .LMDist         (bot_Imdist), 
        .RMDist         (bot_rmdist), 
        .upd_sysregs    (bot_upd_sysregs),

        /* Seven Segmetn Display */
        .dig0           (ssd_d0_out),
        .dig1           (ssd_d1_out),
        .dig2           (ssd_d2_out),
        .dig3           (ssd_d3_out),                        
        .dp             (ssd_dp_out),

        /* Debounced Output */
        .db_btns        (bot_pbtn_db),
        .db_sw          (db_sw),

        /* LEDs */
        .led            (led),

        /* Clock and Reset */
        .clk            (sysclk),
        .reset          (sysreset)
    );

    /********************************* botSIM *********************************/
    bot botSIM(
        .MotCtl_in      (bot_motctl),  
        .LocX_reg       (bot_locX),          
        .LocY_reg       (bot_locY),          
        .Sensors_reg    (bot_sensors),    
        .BotInfo_reg    (bot_botinfo),    
        .LMDist_reg     (bot_Imdist),      
        .RMDist_reg     (bot_rmdist),      
        .upd_sysregs    (bot_upd_sysregs),
        .clk            (sysclk),        
        .reset          (sysreset),
                                        //
        /****** video controller ******/  
        .vid_row        ({2'b0,vc_vid_row_out[9:2]}),
        .vid_col        ({2'b0,vc_vid_col_out[9:2]}),
        .vid_pixel_out  (bot_world_pxl_out)    
    );
    
    /**************************** Debounce module *****************************/
    debounce    DB  (
        .clk            (sysclk),   
        .pbtn_in        ({btnl,btnu,btnr,btnd,btns}),
        .switch_in      (sw),
        .pbtn_db        (db_btns),
        .swtch_db       (db_sw)
    );  
                                                        //
    /********** Seven Segment Display module **********/
     sevensegment SSD (
         // inputs for control signals
         .d0            (ssd_d0_out),
         .d1            (ssd_d1_out),
         .d2            (ssd_d2_out),
         .d3            (ssd_d3_out),
         .dp            (ssd_dp_out),
         // outputs to seven segment display
         .seg           (seg),          
         .an            (an),                
         // clock and reset signals (100 MHz clock, active high reset)
         .clk           (sysclk),
         .reset         (sysreset),
         // ouput for simulation only
         .digits_out    (digits_out)
    );
   /*   
	bot_icon bot_icon_uldr (
	  .clka(sysclk), // input clka
	  .addra(), // input [5 : 0] addra
	  .douta()  // output [31 : 0] douta
	);
	*/

    /************************* Video Controller **************************/	
	VideoController_IF vidCtl (
        .clk100         (sysclk),        
        .reset          (sysreset), 
        .icon_toggle    (db_sw[7]),

        .world_pixel_in (bot_world_pxl_out), 
        .BotInfo_in     (bot_botinfo),     
        .Loc_x_in       (bot_locX),       
        .Loc_y_in       (bot_locY),

        .pxl_row        (vc_vid_row_out),
        .pxl_col        (vc_vid_col_out),       
        .vert_sync      (Vsync),
        .horz_sync      (Hsync),
        .red            (vgaRed),
        .green          (vgaGreen),
        .blue           (vgaBlue[2:1])         	
	);
endmodule
